/*
---
MooTools: the javascript framework

web build:
 - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7

packager build:
 - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff

/*
---

name: Core

description: The heart of MooTools.

license: MIT-style license.

copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/).

authors: The MooTools production team (http://mootools.net/developers/)

inspiration:
  - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
  - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)

provides: [Core, MooTools, Type, typeOf, instanceOf, Native]

...
*/
SPORE.register('core.core',function($ns){

	this.MooTools = {
		version: '1.3.2',
		build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587'
	};
	
	// typeOf, instanceOf
	
	var typeOf = this.typeOf = function(item){
		if (item == null) return 'null';
		if (item.$family) return item.$family();
	
		if (item.nodeName){
			if (item.nodeType == 1) return 'element';
			if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
		} else if (typeof item.length == 'number'){
			if (item.callee) return 'arguments';
			if ('item' in item) return 'collection';
		}
	
		return typeof item;
	};
	
	var instanceOf = this.instanceOf = function(item, object){
		if (item == null) return false;
		var constructor = item.$constructor || item.constructor;
		while (constructor){
			if (constructor === object) return true;
			constructor = constructor.parent;
		}
		return item instanceof object;
	};
	
	// Function overloading
	
	var Function = this.Function;
	
	var enumerables = true;
	for (var i in {toString: 1}) enumerables = null;
	if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
	
	Function.prototype.overloadSetter = function(usePlural){
		var self = this;
		return function(a, b){
			if (a == null) return this;
			if (usePlural || typeof a != 'string'){
				for (var k in a) self.call(this, k, a[k]);
				if (enumerables) for (var i = enumerables.length; i--;){
					k = enumerables[i];
					if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
				}
			} else {
				self.call(this, a, b);
			}
			return this;
		};
	};
	
	Function.prototype.overloadGetter = function(usePlural){
		var self = this;
		return function(a){
			var args, result;
			if (usePlural || typeof a != 'string') args = a;
			else if (arguments.length > 1) args = arguments;
			if (args){
				result = {};
				for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
			} else {
				result = self.call(this, a);
			}
			return result;
		};
	};
	
	Function.prototype.extend = function(key, value){
		this[key] = value;
	}.overloadSetter();
	
	Function.prototype.implement = function(key, value){
		this.prototype[key] = value;
	}.overloadSetter();
	
	// From
	
	var slice = Array.prototype.slice;
	
	Function.from = function(item){
		return (typeOf(item) == 'function') ? item : function(){
			return item;
		};
	};
	
	Array.from = function(item){
		if (item == null) return [];
		return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
	};
	
	Number.from = function(item){
		var number = parseFloat(item);
		return isFinite(number) ? number : null;
	};
	
	String.from = function(item){
		return item + '';
	};
	
	// hide, protect
	
	Function.implement({
	
		hide: function(){
			this.$hidden = true;
			return this;
		},
	
		protect: function(){
			this.$protected = true;
			return this;
		}
	
	});
	
	// Type
	
	var Type = this.Type = function(name, object){
		if (name){
			var lower = name.toLowerCase();
			var typeCheck = function(item){
				return (typeOf(item) == lower);
			};
	
			Type['is' + name] = typeCheck;
			if (object != null){
				object.prototype.$family = (function(){
					return lower;
				}).hide();
				
			}
		}
	
		if (object == null) return null;
	
		object.extend(this);
		object.$constructor = Type;
		object.prototype.$constructor = object;
	
		return object;
	};
	
	var toString = Object.prototype.toString;
	
	Type.isEnumerable = function(item){
		return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
	};
	
	var hooks = {};
	
	var hooksOf = function(object){
		var type = typeOf(object.prototype);
		return hooks[type] || (hooks[type] = []);
	};
	
	var implement = function(name, method){
		if (method && method.$hidden) return;
	
		var hooks = hooksOf(this);
	
		for (var i = 0; i < hooks.length; i++){
			var hook = hooks[i];
			if (typeOf(hook) == 'type') implement.call(hook, name, method);
			else hook.call(this, name, method);
		}
		
		var previous = this.prototype[name];
		if (previous == null || !previous.$protected) this.prototype[name] = method;
	
		if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
			return method.apply(item, slice.call(arguments, 1));
		});
	};
	
	var extend = function(name, method){
		if (method && method.$hidden) return;
		var previous = this[name];
		if (previous == null || !previous.$protected) this[name] = method;
	};
	
	Type.implement({
	
		implement: implement.overloadSetter(),
	
		extend: extend.overloadSetter(),
	
		alias: function(name, existing){
			implement.call(this, name, this.prototype[existing]);
		}.overloadSetter(),
	
		mirror: function(hook){
			hooksOf(this).push(hook);
			return this;
		}
	
	});
	
	new Type('Type', Type);
	
	// Default Types
	
	var force = function(name, object, methods){
		var isType = (object != Object),
			prototype = object.prototype;
	
		if (isType) object = new Type(name, object);
	
		for (var i = 0, l = methods.length; i < l; i++){
			var key = methods[i],
				generic = object[key],
				proto = prototype[key];
	
			if (generic) generic.protect();
	
			if (isType && proto){
				delete prototype[key];
				prototype[key] = proto.protect();
			}
		}
	
		if (isType) object.implement(prototype);
	
		return force;
	};
	
	force('String', String, [
		'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
		'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'
	])('Array', Array, [
		'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
		'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
	])('Number', Number, [
		'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
	])('Function', Function, [
		'apply', 'call', 'bind'
	])('RegExp', RegExp, [
		'exec', 'test'
	])('Object', Object, [
		'create', 'defineProperty', 'defineProperties', 'keys',
		'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
		'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
	])('Date', Date, ['now']);
	
	Object.extend = extend.overloadSetter();
	
	Date.extend('now', function(){
		return +(new Date);
	});
	
	new Type('Boolean', Boolean);
	
	// fixes NaN returning as Number
	
	Number.prototype.$family = function(){
		return isFinite(this) ? 'number' : 'null';
	}.hide();
	
	// Number.random
	
	Number.extend('random', function(min, max){
		return Math.floor(Math.random() * (max - min + 1) + min);
	});
	
	// forEach, each
	
	var hasOwnProperty = Object.prototype.hasOwnProperty;
	Object.extend('forEach', function(object, fn, bind){
		for (var key in object){
			if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);
		}
	});
	
	Object.each = Object.forEach;
	
	Array.implement({
	
		forEach: function(fn, bind){
			for (var i = 0, l = this.length; i < l; i++){
				if (i in this) fn.call(bind, this[i], i, this);
			}
		},
	
		each: function(fn, bind){
			Array.forEach(this, fn, bind);
			return this;
		}
	
	});
	
	// Array & Object cloning, Object merging and appending
	
	var cloneOf = function(item){
		switch (typeOf(item)){
			case 'array': return item.clone();
			case 'object': return Object.clone(item);
			default: return item;
		}
	};
	
	Array.implement('clone', function(){
		var i = this.length, clone = new Array(i);
		while (i--) clone[i] = cloneOf(this[i]);
		return clone;
	});
	
	var mergeOne = function(source, key, current){
		switch (typeOf(current)){
			case 'object':
				if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
				else source[key] = Object.clone(current);
			break;
			case 'array': source[key] = current.clone(); break;
			default: source[key] = current;
		}
		return source;
	};
	
	Object.extend({
	
		merge: function(source, k, v){
			if (typeOf(k) == 'string') return mergeOne(source, k, v);
			for (var i = 1, l = arguments.length; i < l; i++){
				var object = arguments[i];
				for (var key in object) mergeOne(source, key, object[key]);
			}
			return source;
		},
	
		clone: function(object){
			var clone = {};
			for (var key in object) clone[key] = cloneOf(object[key]);
			return clone;
		},
	
		append: function(original){
			for (var i = 1, l = arguments.length; i < l; i++){
				var extended = arguments[i] || {};
				for (var key in extended) original[key] = extended[key];
			}
			return original;
		}
	
	});
	
	// Object-less types
	
	['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
		new Type(name);
	});
	
	// Unique ID
	
	var UID = Date.now();
	
	String.extend('uniqueID', function(){
		return (UID++).toString(36);
	});

});